package mkv.MyGUI;
import processing.core.*; 

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

/**
 * Controller object that registers Draw, Mouse and Key events with PApplet.
 * <p>
 * Since the introduction of MyGUIGroup, most the code from MyGUI has been
 * stripped out to the extent where I decided that MyGUI should now extend MyGUIGroup to
 * regain the same level of functionality.
 * </p>
 * <p>So, the MyGUI controller is infact a fancy version of a MyGUIGroup. That is besides
 * from containing other MyGUI elements as the root of the hierarchy it also has the
 * important task of registering its methods with the parent PApplet so that it, and all
 * its children will respond to mouse and key events as well as automatically drawing them
 * selves to the screen.
 * 
 * @author John Beech
 * @version 0008
 * @see MyGUIGroup
 */
public class MyGUI extends MyGUIGroup {
    /**
     * a reference to the parent processing PApplet where this object was created
     */
    private PApplet _parent;
    
    /**
     * Default class constructor. The default size of the element array will be set to 25,
     * and have x,y coordinates 0,0. This constructor registers Draw, MouseEvent and KeyEvent
     * with the parent processing PApplet.
     *  
     * @param parent  the processing PApplet where all elements will be drawn to
     */ 
    public MyGUI(PApplet parent) {
        super(parent, 0, 0);
        parent.registerMouseEvent(this);
        parent.registerDraw(this);
        parent.registerKeyEvent(this);
        this._parent = parent;
    }
    
    /**
     * Class constructor where the size of the element array can be specified.
     * The x,y coordinates will be set to 0,0. This constructor registers Draw,
     * MouseEvent and KeyEvent with the parent processing PApplet.
     * 
     * @param parent  the processing PApplet where all elements will be drawn to
     * @param size    size of element array. The default size is 25.
     */
    public MyGUI(PApplet parent, int size) {
        super(parent, 0, 0, size);
        parent.registerMouseEvent(this);
        parent.registerDraw(this);
        parent.registerKeyEvent(this);
        this._parent = parent;
    }
    /**
     * Class constructor where the size of the element array can be specified as well
     * as a reference to a MyGUIStyle object. Alternatively you can call one of the above
     * default constructors and then use MyGUI.getStyle() to return the current style in use
     * and modify it from there.
     * 
     * @param parent  the processing PApplet where all elements will be drawn to
     * @param size    size of element array. The default size is 25.
     * @param style		the style object used by all MyGUI elements when they draw themselves
     */
    public MyGUI(PApplet parent, int size, MyGUIStyle style) {
        super(parent, 0, 0, size, style);
        parent.registerMouseEvent(this);
        parent.registerDraw(this);
        parent.registerKeyEvent(this);
        this._parent = parent;
    }
    
    /**
     * Class constructor with a reference to a custom MyGUIStyle object. Alternatively
     * you can call one of the above default constructors and then use MyGUI.getStyle()
     * to return the current style in use and modify it from there.
     * 
     * @param parent  the processing PApplet where all elements will be drawn to
     * @param style		the style object used by all MyGUI elements when they draw themselves
     */
    public MyGUI(PApplet parent, MyGUIStyle style) {
        super(parent, 0, 0, style);
        parent.registerMouseEvent(this);
        parent.registerDraw(this);
        parent.registerKeyEvent(this);
        this._parent = parent;
    }
    
    /**
     * Recalls Mouse events based on type. This method will recall mousePressed,
     * mouseReleased and mouseDragged events when a MouseEvent is detected in the
     * parent PApplet.
     */
    public void mouseEvent(MouseEvent e) {
        // Recall mouse events based on type
        if(e.getID() == MouseEvent.MOUSE_PRESSED) mousePressed();
        else
            if(e.getID() == MouseEvent.MOUSE_RELEASED) mouseReleased();
            else
                if(e.getID() == MouseEvent.MOUSE_DRAGGED) mouseDragged();
    }  
    
    /**
     * Recalls Key events based on type. This method will recall keyPressed, keyReleased
     * and keyTyped events when a KeyEvent is detected in the parent PApplet.
     */
    public void keyEvent(KeyEvent e) {
        // Recall key events based on types
        if(e.getID() == KeyEvent.KEY_PRESSED) keyPressed(e);
        else
            if(e.getID() == KeyEvent.KEY_RELEASED) keyReleased(e);
            else
                if(e.getID() == KeyEvent.KEY_TYPED) keyTyped(e);
    }
    
    /**
     * Returns the enabled or disabled state of this object. 
     * Because MyGUI objects do not have MyGUIObject parents, this method overides the MyGUIObject version.
     * 
     * @return returns true if the object is disabled, false if it is enabled
     */
    public boolean isDisabled() {
        return _disabled;
    }
    
    /**
     * Updates local mouse coordinates tmouseX and tmouseY.
     * Taken from the check for hit code, this calculates the local mouse coordinates
     * after translation, rotation and scaling.
     * <p>
     * Because the MyGUI controller is considered a parent object that sits above all others
     * then it has a customized updateLocalMouse() method that uses PApplet mouseX, mouseY
     * instead of _parent.tmouseX, _parent.tmouseY.
     */
    public void updateLocalMouse() {
        // This code was taken from MyGUIObject.updateLocalMouse() and altered
        // to support the customMouse state. It calculates the apparent non rotated
        // and non translated mouse coordinates.
        if(customMouse) {
            // If a custom mouse is provided, it will likely still need rotating
            if(_rotation != 0) {
                float cosval = _root.cos(-PApplet.radians(_rotation));
                float sinval = _root.sin(-PApplet.radians(_rotation));
                int rotationPointX = (tmouseX - _x);
                int rotationPointY = (tmouseY - _y);
                tmouseX = PApplet.round(rotationPointX * cosval - rotationPointY * sinval * _scale)+_x;
                tmouseY = PApplet.round(rotationPointX * sinval + rotationPointY * cosval * _scale)+_y;
            }
        } else
        if(_rotation != 0) {
            float cosval = _root.cos(-PApplet.radians(_rotation));
            float sinval = _root.sin(-PApplet.radians(_rotation));
            int rotationPointX = (_parent.mouseX - _x);
            int rotationPointY = (_parent.mouseY - _y);
            tmouseX = PApplet.round(rotationPointX * cosval - rotationPointY * sinval * _scale);
            tmouseY = PApplet.round(rotationPointX * sinval + rotationPointY * cosval * _scale);
        } 
        else {
            // No rotation, just use the values
            tmouseX = PApplet.round((_parent.mouseX - _x) * _scale);
            tmouseY = PApplet.round((_parent.mouseY - _y) * _scale);
        }
    }
}
